package com.tgu.home_action.service.impl;


import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.sms.v20190711.models.SendStatus;
import com.tgu.home_action.dao.FamilyMapper;
import com.tgu.home_action.dao.LogMapper;
import com.tgu.home_action.pojo.Family;
import com.tgu.home_action.pojo.ResponseData;
import com.tgu.home_action.pojo.exception.IMException;
import com.tgu.home_action.pojo.state.RedisHeader;
import com.tgu.home_action.pojo.state.ResponseState;
import com.tgu.home_action.service.FamilyService;
import com.tgu.home_action.service.utils.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Validated
@Service
public class FamilyServiceImpl implements FamilyService {
    @Autowired
    private MessageService messageService;
    @Autowired
    private IMService imService;
    @Autowired
    private AliYunService aliyunService;
    @Autowired
    private JwtService jwtService;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WXService wxService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private FamilyMapper familyMapper;
    @Autowired
    private LogMapper logMapper;
    @Autowired
    private Logger logger;

    final String templateId = "1858351";

    /**
     * 家属登录
     */
    @Override
    @Transactional
    public ResponseData<Family> login(@NotNull(message = "code不能为空") String code) {
        Map<String, Object> data = wxService.getFamilyOpenId(code);
        String openid = (String) data.get("openid");
        System.out.println("openid:"+openid);
        if (openid == null) {
            switch ((int) data.get("errcode")) {
                case -1:
                    logger.error("查询openid时系统繁忙，请稍后再试");
                    return new ResponseData<Family>("系统繁忙，请稍候再试", -1);
                case 40029:
                    logger.error("查询openid时code无效");
                    return new ResponseData<Family>("code无效", 40029);
                case 45011:
                    logger.error("请求频率过高");
                    return new ResponseData<Family>("请求频率过高", 45011);
                case 40163:
                    logger.error("查询openid时code已经被使用");
                    return new ResponseData<Family>("code已经被使用", 40163);
                default:
                    return new ResponseData<Family>("openid获取失败", ResponseState.ERROR.getValue());
            }
        }
        Family family = familyMapper.getByOpenid(openid);
        if (family == null) {
            family = new Family();
            family.setOpenid(openid);
            family.setRegisterTime(new Timestamp(new Date().getTime()));
            family.setState((short) 1);
            familyMapper.insertFamily(family);
        }
        //判断账号是否违规
        if (family.getState() != 1) {
            return new ResponseData<>(ResponseState.ACCOUNT_IS_ILLEGAL.getMessage(), ResponseState.ACCOUNT_IS_ILLEGAL.getValue());
        }
        //储存sessionKey
        String sessionKey = (String) data.get("session_key");
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_SESSION_KEY.getHeader() + family.getId(), sessionKey);
        //储存token
        String accessToken = jwtService.getAccessToken(family.getId(), "family");
        String refreshToken = jwtService.getRefreshToken(family.getId(), "family");
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_TOKEN.getHeader() + family.getId(), accessToken);
        stringRedisTemplate.expire(RedisHeader.FAMILY_TOKEN.getHeader() + family.getId(), 2, TimeUnit.HOURS);
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_REFRESH_TOKEN.getHeader() + family.getId(), refreshToken);
        stringRedisTemplate.expire(RedisHeader.FAMILY_REFRESH_TOKEN.getHeader() + family.getId(), 15, TimeUnit.DAYS);
        return new ResponseData<Family>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), accessToken, refreshToken, family);
    }

    @Override
    @Transactional
    public ResponseData<Object> updateUserinfo(@NotNull(message = "encryptedData不能为空") String encryptedData, @NotNull(message = "iv不能为空") String iv, Family familyUser) {
        Family family = new Family();
        familyUser = familyMapper.getById(familyUser.getId());
        String sessionKey = stringRedisTemplate.opsForValue().get(RedisHeader.FAMILY_SESSION_KEY.getHeader() + familyUser.getId());
        Map<String, Object> data = wxService.getUserInfo(encryptedData, sessionKey, iv);
        family.setAllUserinfo(data);
        if (familyUser.getAvatarUrl() == null) {
            family.setId(familyUser.getId());
            familyMapper.updateUserinfo(family);
            return new ResponseData<Object>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
        }
        return new ResponseData<Object>("信息未变更", ResponseState.SUCCESS.getValue());
    }

    /**
     * 更新Token
     *
     * @param refreshToken:refreshToken
     * @return token
     */
    @Override
    public ResponseData<Object> refreshToken(@NotNull(message = "refreshToken不能为空") String refreshToken) {
        Family family = (Family) jwtService.getUser(refreshToken);
        if (family == null) {
            return new ResponseData<>(ResponseState.REFRESH_TOKEN_IS_ERROR.getMessage(), ResponseState.REFRESH_TOKEN_IS_EXPIRED.getValue());
        }
        String rightToken = stringRedisTemplate.opsForValue().get(RedisHeader.FAMILY_REFRESH_TOKEN.getHeader() + family.getId());
        if (!refreshToken.equals(rightToken)) {
            return new ResponseData<>(ResponseState.REFRESH_TOKEN_IS_ERROR.getMessage(), ResponseState.REFRESH_TOKEN_IS_ERROR.getValue());
        }
        String newAccessToken = jwtService.getAccessToken(family.getId(), "family");
        String newRefreshToken = jwtService.getRefreshToken(family.getId(), "family");
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_TOKEN.getHeader() + family.getId(), newAccessToken);
        stringRedisTemplate.expire(RedisHeader.FAMILY_TOKEN.getHeader() + family.getId(), 2, TimeUnit.HOURS);
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_REFRESH_TOKEN.getHeader() + family.getId(), newRefreshToken);
        stringRedisTemplate.expire(RedisHeader.FAMILY_REFRESH_TOKEN.getHeader() + family.getId(), 15, TimeUnit.DAYS);
        return new ResponseData<Object>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), newAccessToken, newRefreshToken);

    }

    /**
     * 绑定手机获取验证码
     *
     * @param phone：手机号
     * @param familyUser：当前登录的用户
     */
    @Override
    public ResponseData<Object> getBindCode(String phone, Family familyUser) {
        String code = StringService.getCode();
        try {
            SendStatus sendStatus=messageService.sendMessage(phone,templateId,new String[]{code});
            if(!sendStatus.getCode().equals("Ok")){
                return new ResponseData<>("短信发送失败",500);
            }
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            return new ResponseData<>("短信发送失败",500);
        }
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_BIND_CODE.getHeader() + phone + familyUser.getId(), code);
        stringRedisTemplate.expire(RedisHeader.FAMILY_BIND_CODE.getHeader() + phone + familyUser.getId(), 5, TimeUnit.MINUTES);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 修改手机获取验证码
     *
     * @param phone：手机号
     * @param familyUser：当前登录的用户
     */
    @Override
    public ResponseData<Object> getUpdateCode(String phone, Family familyUser) {
        String code=StringService.getCode();
        System.out.println("==================================");
        try {
            SendStatus sendStatus=messageService.sendMessage(phone,templateId,new String[]{code});
            if(!sendStatus.getCode().equals("Ok")){
                return new ResponseData<>("短信发送失败",500);
            }
        } catch (TencentCloudSDKException e) {
            e.printStackTrace();
            return new ResponseData<>("短信发送失败",500);
        }
        System.out.println("==================================");
        stringRedisTemplate.opsForValue().set(RedisHeader.FAMILY_UPDATE_CODE.getHeader() + phone + familyUser.getId(), code);
        stringRedisTemplate.expire(RedisHeader.FAMILY_UPDATE_CODE.getHeader() + phone + familyUser.getId(), 5, TimeUnit.MINUTES);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 完善信息
     */
    @Override
    public ResponseData<Object> bindPhone(@NotNull(message = "phone不能为空") String phone, @NotNull(message = "code不能为空") String code, Family familyUser) {
        familyUser = familyMapper.getById(familyUser.getId());
        if (familyUser.getPhone() == null) {
            String rightCode = stringRedisTemplate.opsForValue().get(RedisHeader.FAMILY_BIND_CODE.getHeader() + phone + familyUser.getId());
            if (rightCode == null) {
                return new ResponseData<>(ResponseState.CODE_NOT_EXIST.getMessage(), ResponseState.CODE_NOT_EXIST.getValue());
            }
            if (!rightCode.equals(code)) {
                return new ResponseData<>(ResponseState.CODE_IS_ERROR.getMessage(), ResponseState.CODE_IS_ERROR.getValue());
            }
            familyUser.setPhone(phone);
            familyMapper.updatePhone(familyUser);
            stringRedisTemplate.delete(RedisHeader.FAMILY_BIND_CODE.getHeader() + phone + familyUser.getId());
            return new ResponseData<>("手机号绑定成功", ResponseState.SUCCESS.getValue());
        } else {
            String rightCode = stringRedisTemplate.opsForValue().get(RedisHeader.FAMILY_UPDATE_CODE.getHeader() + phone + familyUser.getId());
            if (rightCode == null) {
                return new ResponseData<>(ResponseState.CODE_NOT_EXIST.getMessage(), ResponseState.CODE_NOT_EXIST.getValue());
            }
            if (!rightCode.equals(code)) {
                return new ResponseData<>(ResponseState.CODE_IS_ERROR.getMessage(), ResponseState.CODE_IS_ERROR.getValue());
            }
            familyUser.setPhone(phone);
            familyMapper.updatePhone(familyUser);
            stringRedisTemplate.delete(RedisHeader.FAMILY_UPDATE_CODE.getHeader() + phone + familyUser.getId());
            return new ResponseData<>("手机号修改成功", ResponseState.SUCCESS.getValue());
        }

    }

    /**
     * 上传图片
     */
    @Override
    public ResponseData<String> uploadPhoto(MultipartFile photo, Family familyUser) throws IOException {
        InputStream inputStream = photo.getInputStream();
        if (!FileService.isImage(inputStream)) {
            return new ResponseData<>(ResponseState.FILE_FORMAT_ERROR.getMessage(), ResponseState.FILE_FORMAT_ERROR.getValue());
        }
        photo.getOriginalFilename();
        String url = aliyunService.uploadFile(photo.getInputStream(), "family/" + familyUser.getId() + "/" + StringService.getRandomString() + FileService.getFileSuffix(photo.getOriginalFilename()));
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), url);
    }

    /**
     * 家属更换头像
     */
    @Override
    public ResponseData<String> updateAvatar(@NotNull(message = "avatarUrl不能为空") String avatarUrl, Family familyUser) {
        familyUser.setAvatarUrl(avatarUrl);
        familyMapper.updateUserinfo(familyUser);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 获取个人信息
     */
    @Override
    public ResponseData<Family> getFamily(Family familyUser) {
        Family family = familyMapper.getById(familyUser.getId());
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), family);
    }

    /**
     * 获取IM的UserSig
     */
    @Override
    public ResponseData<String> getUserSig(Family family) throws IMException {
        Boolean isExist = imService.accountCheck("family_" + family.getId());
        if (!isExist) {
            imService.insertUser("family_" + family.getId(), familyMapper.getNameById(family.getId()), null);
            imService.setMessage("family_" + family.getId(), "family", family.getId());
        }
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), imService.getUserSig("family_" + family.getId()));
    }

    /**
     * 修改信息
     */
    @Override
    public ResponseData<Object> updateInfo(Family family, Family familyUser) {
        family.setId(familyUser.getId());
        familyMapper.updateInformation(family);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue());
    }

    /**
     * 通过ID查询
     */
    @Override
    public ResponseData<Family> getById(Integer id) {
        Family family = familyMapper.getById(id);
        return new ResponseData<>(ResponseState.SUCCESS.getMessage(), ResponseState.SUCCESS.getValue(), family);
    }
}
